#include "object.h"
#include "../gameprog.h"

using namespace std;

/*------------------------DOCUMENTATION------------------------//
// OBJECT.CPP                                                  //
//    Contains all functions that belong to all objects        //
// Movement Functions:                                         //
//    jump: moves object to given coordinates                  //
//    move: like jump but based on velocity vector             //
//    getSpeed: returns magnitude of velocity vector           //
//    getDirection: returns direction of velocity vector       //
//    setSpeed: sets magnitude of velocity vector              //
//    setDirection: sets direction of velocity vector          //
//    setVelocityXY: sets velocity vector by component         //
//    setVelocitySpDir: sets velocity by speed, direction      //
//    getForceMagnitude: returns magnitude of force vector     //
//    getForceDirection: returns direction of force vector     //
//    updateVelocity: updates velocity from force              //
//    updateForce: updates net force from forces array         //
//    newForceXY: adds new force to forces array by component  //
//    newForceMagDir: adds new force by magnitude, direction   //
//    checkForce: checks forces array for refreshing forces    //
//    removeForce: removes a force from forces array           //
//-------------------------------------------------------------*/

/*typedef float locvar;
typedef float massvar;

const double PI = 3.14159265;
const float dt = .001;


void powr(Item& base, int e)
{
	Item counter = 1;
	for(int i = 0; i < e; i++)
	{
		counter *= base;
		cout << counter << endl;
	}
	base = counter;
}
*/

void object::jump(locvar tx, locvar ty)
{
    x = tx;
    y = ty;
}
void object::move() { jump(x + dx * DT, y + dy * DT); }

locvar object::getSpeed()const { return std::pow((std::pow(dx,locvar(2)) + std::pow(dy,locvar(2))),locvar(.5)); }
locvar object::getDirection()const { return atan2(dy,dx); }
        
void object::setSpeed(locvar nspeed)
{
    if ( getSpeed() != 0 )
    {
        locvar multiplier = nspeed/getSpeed();
        dx *= multiplier;
        dy *= multiplier;
    }
    else
    {
        dx = nspeed * cos(getDirection());
        dy = nspeed * sin(getDirection());
    }
}
void object::setDirection(locvar ndirection)
{
    locvar ux = cos(ndirection);
    locvar uy = sin(ndirection);
    locvar tempspeed = getSpeed();
    dx = ux * tempspeed;
    dy = uy * tempspeed;
}
void object::setVelocityXY(locvar ndx, locvar ndy)
{
    dx = ndx;
    dy = ndy;
}
void object::setVelocitySpDir(locvar nspeed, locvar ndirection)
{
    locvar ux = cos(ndirection);
    locvar uy = sin(ndirection);
    dx = ux * nspeed;
    dy = uy * nspeed;
}

locvar object::getForceMagnitude()const { return sqrt(pow(forces.netForce.x,2)+pow(forces.netForce.y,2)); }
locvar object::getForceDirection()const { return atan2(forces.netForce.y,forces.netForce.x); }

locvar object::getDistancePoint(locvar pointx, locvar pointy)
{
    return sqrt(pow(pointx - x,2) + pow(pointy - y,2));
}

locvar object::getDistanceOrigin()
{
    return sqrt(pow(ORIGIN_X - x, 2) + pow(ORIGIN_Y - y, 2));
}

locvar object::getDistanceObject(idtype other)
{
    return sqrt(pow(objects[other].x - x,2) + pow(objects[other].y - y,2));
}

locvar object::getDirectionPoint(locvar pointx, locvar pointy)
{
    return atan2((pointx - x), (pointy - y));
}

locvar object::getDirectionOrigin()
{
    return atan2((ORIGIN_X - x), (ORIGIN_Y - y));
}

locvar object::getDirectionObject(idtype other)
{
    return atan2((objects[other].x - x),(objects[other].y - y));
}

void object::updateVelocity()
{
    dx += forces.netForce.x/mass * DT;
    dy += forces.netForce.y/mass * DT;
}

void object::newForceXY(locvar nx, locvar ny, bool refresher, bool updater)
{
    forces.newForce(nx,ny,refresher,updater);
}

void object::newForceMagDir(locvar nmag, locvar ndir, bool refresher, bool updater)
{
    locvar ux, uy;
    
    ux = cos(ndir);
    uy = sin(ndir);
    
    forces.newForce(ux*nmag,uy*nmag,refresher,updater);
}

void object::addQuickGravity()
{
    newForceMagDir(G*mass,3*PI/2,0,1);
}
